﻿Function Remove-EventHandler
{
  [CmdletBinding(DefaultParameterSetName="FriendlyName")]
  param
  (
    [parameter(Position=0,
               Mandatory=$True,
               ParameterSetName="Number")]
    [int]
    $Number = -1,

    [parameter(Position=1,
               Mandatory=$True,
               ParameterSetName="FriendlyName")]
    [String]
    $FriendlyName,

    [parameter(Position=1,
               Mandatory=$True,
               ParameterSetName="Id")]
    [System.Guid]
    $Id
  )

  Begin
  {
    # Lock the handler list XML file while removing the event handler.
    $Created = $False
    $Script:HandlerMutex = New-Object System.Threading.Mutex($True,"eventlib_write_handler_xml",[ref]$Created)

    if ($Created -eq $False)
    {
      try `
      {
        $Lock = $Script:HandlerMutex.WaitOne(2000)
      }
      catch [System.Threading.AbandonedMutexException] `
      {
        Write-Warning "Caught AbandonedMutexException.  Consider checking the Event Handler list for consistency."
      }
    }
    else
    {
      $Lock = $True
    }

    if ($Lock -eq $False)
    {
      $Exception = New-Object System.TimeoutException "Timed out waiting to lock the eventlib_write_handler_xml mutex."
      throw $Exception
    }
  }

  Process
  {
    $HandlerList = $(Get-EventHandler)

    if ($HandlerList -eq $Null)
    {
      $HandlerList = @()
    }
    elseif ($HandlerList -isnot [system.array])
    {
      $HandlerList = @($HandlerList)
    }


    # Find the handler.
    if ($Number -ge 0)
    {
      $ToRemove = Get-EventHandler -Number $Number
    }
    elseif ($FriendlyName.Length -gt 0)
    {
      $ToRemove = Get-EventHandler -FriendlyName $FriendlyName
    }
    elseif ($Id -ne $Null)
    {
      $ToRemove = Get-EventHandler -Id $Id
    }

    # If exactly one handler was found, it's the one to remove
    if ($ToRemove.Count -eq 1)
    {
      # Ensure that the handler isn't referenced in any event groups
      $GroupList = Get-EventGroup

      foreach ($Group in $GroupList)
      {
        if ($Group.AssignedHandlers -contains $ToRemove.Id)
        {
          $Exception = New-Object System.ArgumentException "Cannot remove this handler: it is still assigned in Event Group '$($Group.FriendlyName)'."
          throw $Exception
        }
      }

      $HandlerList = $HandlerList | Where-Object {$_.Id -ne $ToRemove.Id}
      Export-Clixml -Path $Script:HandlerXMLPath -InputObject $HandlerList
    }
    else
    {
      $Exception = New-Object System.ArgumentException "Fatal error.  $($ToRemove.Count) handlers matched the given parameters.  Check the handler XML file."
      throw $Exception
    }
  }

  End
  {
    $Script:HandlerMutex.ReleaseMutex()
  }
}